#include "hiredis/hiredis.h"
#include<string>
#include <stdint.h>
#include<vector>
using namespace std;

#ifndef __SYNC_REDIS_CLIENT__
#define __SYNC_REDIS_CLIENT__





	//synchronize redis client.
	class RedisClient
	{
		public:
			RedisClient(string _ip,int _port);
			~RedisClient();

			//add BackupIpPort
			void addBackupIpPort(string ip, int port); 
			//clear all Ip Port 
			void clearIpPort(string ip, int port);
			bool connect(string ip, int port);
			// return NULL if redis is not connected. 
			struct redisReply* redisCommand(const char *format, ...);
			struct redisReply* redisCommandWithArgv(vector<string> &cmds);

			//every reply after processing. Must be released by this.
			void freeReply(redisReply *reply);

			string getLastError();

			// check if key: salive 's value update every 10 second.
			// if not alive. automatically switch redis.
			// return True. if it's alive
			// if not alive switch success return True,otherwise return false.
			bool checkAlive();


			//switch to use other Ip Ports.
			bool switchRedis();

			// set redis read/write timeout, unit: ms(=1/1000 second)
			bool setTimeout(int ms);

			bool isConnected();

		protected:
			//current ip port
			string m_ip;
			int m_port; 
			//default time out 2 seconds
			int m_connectTimeout;

			//hiredis context
			struct redisContext *m_pContext;
			vector< pair<string,uint32_t> > m_ipPorts;
			bool m_bConnected;
			//index of current ip port in m_ipPorts
			size_t m_curIpPortIdx;
			int m_lastAliveValue;
			string m_lastErrorMsg;
			// timeout
			int m_timeout;
			//collect network error and redis error.
			void collectLastError(redisReply *reply=NULL);

		public:
			//convert obj to string. use ostringstream.
			template<class T>
				string toString(T input);
			//split a string use delim
			void split(string& s, string& delim,std::vector<string>* ret);
	};


#endif
